using System.Activities;
using System.Activities.Statements;
using Headsight.BPMN2WF.Transformation;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Headsight.BPMN2WF.WF.Simplification
{
    [TestClass]
    public class WFSimplifier_SequenceTest : WFSimplifier_TestFixture<WFSimplifierSequence>
    {
        private Sequence _sequence;

        protected override WFSimplifierSequence CreateSut()
        {
            _sequence = new Sequence();
            return new WFSimplifierSequence();
        }

        private static BPMNTransformationResult CreateBPMNTransformationResult(Activity activity)
        {
            return new BPMNTransformationResult(activity, activity, activity);
        }

        [TestMethod]
        public void Probe_inco_Sequence()
        {
            Assert.AreEqual(true, _sut.Probe(_ctx, CreateBPMNTransformationResult(_sequence)));
        }

        [TestMethod]
        public void Probe_inco_any_other_Activity_but_not_Sequence()
        {
            Assert.AreEqual(false, _sut.Probe(_ctx, CreateBPMNTransformationResult(new Throw())));
        }

        [TestMethod]
        public void Simplify_inco_empty_Sequence()
        {
            var actual = _sut.Simplify(_ctx, CreateBPMNTransformationResult(_sequence));

            Assert.AreSame(_sequence, actual.Result);
            Assert.AreSame(_sequence, actual.FlowIn);
            Assert.AreSame(_sequence, actual.FlowOut);
        }

        [TestMethod]
        public void Simplify_inco_Sequence_of_non_Sequences()
        {
            var activity1 = new Throw();
            var activity2 = new Throw();

            var sequence = new Sequence();
            sequence.Activities.Add(activity1);
            sequence.Activities.Add(activity2);

            var transformationResult = _sut.Simplify(_ctx, new BPMNTransformationResult(sequence, activity1, activity2));

            var actual = _sut.Simplify(_ctx, transformationResult);

            Assert.AreSame(sequence, actual.Result);
            Assert.AreSame(activity1, actual.FlowIn);
            Assert.AreSame(activity2, actual.FlowOut);
        }

        [TestMethod]
        public void Simplify_inco_Sequence_of_Sequences_verf_child_Sequences_are_simplified_into_parent_Sequence()
        {
            var activity1 = new Throw();
            var activity2 = new Throw();
            var activity_seq1_1 = new Throw();
            var activity_seq1_2 = new Throw();
            var activity_seq2_1 = new Throw();
            var activity_seq2_2 = new Throw();

            var sequence = CreateSequence(
                activity1, 
                CreateSequence(activity_seq1_1, activity_seq1_2), 
                activity2, 
                CreateSequence(activity_seq2_1, activity_seq2_2));

            var transformationResult = _sut.Simplify(_ctx, new BPMNTransformationResult(sequence, activity1, activity2));

            var actualSequence = (Sequence)transformationResult.Result;

            Assert.AreEqual(6, actualSequence.Activities.Count);
            Assert.AreSame(activity1, actualSequence.Activities[0]);
            Assert.AreSame(activity_seq1_1, actualSequence.Activities[1]);
            Assert.AreSame(activity_seq1_2, actualSequence.Activities[2]);
            Assert.AreSame(activity2, actualSequence.Activities[3]);
            Assert.AreSame(activity_seq2_1, actualSequence.Activities[4]);
            Assert.AreSame(activity_seq2_2, actualSequence.Activities[5]);
        }

        [TestMethod]
        public void Simplify_inco_Sequence_of_Sequences_inco_child_Sequence_at_position_0_verf_results_FlowIn_node()
        {
            var activity1 = new Throw();
            var activity2 = new Throw();
 
            var sequence = CreateSequence(CreateSequence(activity1), activity2);

            var transformationResult = _sut.Simplify(_ctx, new BPMNTransformationResult(sequence, activity1, activity2));

            Assert.AreSame(activity1, transformationResult.FlowIn);
            Assert.AreSame(activity2, transformationResult.FlowOut);
        }

        [TestMethod]
        public void Simplify_inco_Sequence_of_Sequences_inco_child_Sequence_at_last_position_verf_results_FlowIn_node()
        {
            var activity1 = new Throw();
            var activity2 = new Throw();

            var sequence = CreateSequence(activity2, CreateSequence(activity1));

            var transformationResult = _sut.Simplify(_ctx, new BPMNTransformationResult(sequence, activity1, activity2));

            Assert.AreSame(activity2, transformationResult.FlowIn);
            Assert.AreSame(activity1, transformationResult.FlowOut);
        }

        [TestMethod]
        public void Simplify_inco_Sequence_of_Sequences_inco_child_Sequence_at_last_position_verf_results_FlowIn_node_inco_no_FlowOut()
        {
            var activity1 = new Throw();
            var activity2 = new Throw();

            var sequence = CreateSequence(activity2, CreateSequence(activity1));

            var transformationResult = _sut.Simplify(_ctx, new BPMNTransformationResult(sequence, activity1, null));

            Assert.AreSame(activity2, transformationResult.FlowIn);
            Assert.AreEqual(null, transformationResult.FlowOut);
        }
    }
}
